import pytest
import requests


@pytest.fixture
def base_url():
    return "http://127.0.0.1:8080"


def test_successful_account_retrieval(base_url):
    account_id = 1

    cookies = {"id": str(account_id)}

    response = requests.get(f"{base_url}/accounts/{account_id}", cookies=cookies)

    assert response.status_code == 200
    assert "id" in response.json()
    assert "firstName" in response.json()
    assert "lastName" in response.json()
    assert "email" in response.json()


def test_invalid_auth_cookie(base_url):
    cookies = {"id": "2"}

    response = requests.get(f"{base_url}/accounts/1", cookies=cookies)

    assert response.status_code == 401


@pytest.mark.parametrize("invalid_account_id", [None, 0, -1])
def test_invalid_account_id(base_url, invalid_account_id):
    cookies = {"id": "1"}
    response = requests.get(
        f"{base_url}/accounts/{invalid_account_id}", cookies=cookies
    )

    assert response.status_code == 400


def test_nonexistent_account(base_url):
    account_id = 1
    cookies = {"id": str(account_id)}
    response = requests.get(f"{base_url}/accounts/999", cookies=cookies)

    assert response.status_code == 404


@pytest.fixture
def auth_cookies():
    return {"id": "1"}


def test_successful_account_search(base_url, auth_cookies):
    search_params = {
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@example.com",
        "from": 0,
        "size": 10,
    }

    response = requests.get(
        f"{base_url}/accounts/search", params=search_params, cookies=auth_cookies
    )

    assert response.status_code == 200

    assert isinstance(response.json(), list)
    for account in response.json():
        assert "id" in account
        assert "firstName" in account
        assert "lastName" in account
        assert "email" in account


def test_invalid_auth_search(base_url):
    response = requests.get(f"{base_url}/accounts/search")

    assert response.status_code == 401


@pytest.mark.parametrize(
    "invalid_params",
    [
        {"from": -1, "size": 10},
        {"from": 0, "size": -10},
        {"from": -1, "size": -10},
        {"from": "invalid", "size": 10},
        {"from": 0, "size": "invalid"},
    ],
)
def test_invalid_request_params(base_url, invalid_params, auth_cookies):
    response = requests.get(
        f"{base_url}/accounts/search", params=invalid_params, cookies=auth_cookies
    )

    assert response.status_code == 400


def test_empty_search_result(base_url, auth_cookies):
    search_params = {
        "firstName": "Nonexistent",
        "lastName": "Account",
        "email": "nonexistent@example.com",
        "from": 0,
        "size": 10,
    }
    response = requests.get(
        f"{base_url}/accounts/search", params=search_params, cookies=auth_cookies
    )

    assert response.status_code == 200

    assert len(response.json()) == 0


def test_account_search_sorting(base_url, auth_cookies):
    search_params = {
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@example.com",
        "from": 0,
        "size": 10,
    }

    response = requests.get(
        f"{base_url}/accounts/search", params=search_params, cookies=auth_cookies
    )

    assert response.status_code == 200

    account_ids = [account["id"] for account in response.json()]
    assert account_ids == sorted(account_ids)


def test_successful_account_update(base_url, auth_cookies):
    update_data = {
        "firstName": "NewFirstName",
        "lastName": "NewLastName",
        "email": "new.email@example.com",
        "password": "newpassword",
    }

    account_id = auth_cookies["id"]

    response = requests.put(
        f"{base_url}/accounts/{account_id}", json=update_data, cookies=auth_cookies
    )

    assert response.status_code == 200

    assert "id" in response.json()
    assert "firstName" in response.json()
    assert "lastName" in response.json()
    assert "email" in response.json()


def test_invalid_auth_edit(base_url):
    account_id = 123
    update_data = {
        "firstName": "NewFirstName",
        "lastName": "NewLastName",
        "email": "new.email@example.com",
        "password": "newpassword",
    }

    response = requests.put(f"{base_url}/accounts/{account_id}", json=update_data)

    assert response.status_code == 401


def test_update_other_account(base_url, auth_cookies):
    account_id = 999
    update_data = {
        "firstName": "NewFirstName",
        "lastName": "NewLastName",
        "email": "new.email@example.com",
        "password": "newpassword",
    }

    response = requests.put(
        f"{base_url}/accounts/{account_id}", json=update_data, cookies=auth_cookies
    )

    assert response.status_code == 403


def test_existing_email(base_url, auth_cookies):
    account_id = auth_cookies["id"]
    update_data = {
        "firstName": "NewFirstName",
        "lastName": "NewLastName",
        "email": "new.email@example.com",
        "password": "newpassword",
    }

    response = requests.put(
        f"{base_url}/accounts/{account_id}", json=update_data, cookies=auth_cookies
    )

    assert response.status_code == 409


def test_successful_account_deletion(base_url, auth_cookies):
    account_id = auth_cookies["id"]
    response = requests.delete(
        f"{base_url}/accounts/{account_id}", cookies=auth_cookies
    )
    assert response.status_code == 200

    user_data = {
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@example.com",
        "password": "securepassword",
    }

    requests.post(f"{base_url}/registration", json=user_data)


def test_invalid_auth_delete(base_url):
    account_id = 123
    response = requests.delete(f"{base_url}/accounts/{account_id}")
    assert response.status_code == 401


def test_delete_nonexistent_account(base_url):
    account_id = 999
    auth_cookies = {"id": "2"}
    response = requests.delete(
        f"{base_url}/accounts/{account_id}", cookies=auth_cookies
    )
    assert response.status_code == 403


def test_delete_other_account(base_url):
    account_id = 999
    auth_cookies = {"id": "2"}
    response = requests.delete(
        f"{base_url}/accounts/{account_id}", cookies=auth_cookies
    )
    assert response.status_code == 403
